// ==============================================================
// BeaconArray.cpp
// Part of the ORBITER VISUALISATION PROJECT (OVP)
// Released under GNU General Public License
// Copyright (C) 2012 Jarmo Nikkanen
// ==============================================================

#include "FileParser.h"
#include "D3D9Config.h"
#include "Log.h"

// ===========================================================================================
//
FileParser::FileParser(const char *scenario)
{
	_TRACE;
	eidx = 0;
	entry = new ObjEntry[2048];
	for (int i=0;i<2048;i++) {
		entry[i].hObj = NULL;
		entry[i].file = NULL;
		entry[i].Albedo = _V(1,1,1);
	}
	ParseScenario(scenario);
}

// ===========================================================================================
//
FileParser::~FileParser()
{
	for (DWORD i=0;i<eidx;i++) if (entry[i].file) delete[] entry[i].file;
	delete[] entry;
}

// ===========================================================================================
//
const char *FileParser::GetConfigFile(OBJHANDLE hObj)
{
	for (DWORD i=0;i<eidx;i++) if (entry[i].hObj==hObj) return entry[i].file;
	return NULL;
}

// ===========================================================================================
//
VECTOR3 FileParser::GetAlbedo(OBJHANDLE hObj)
{
	for (DWORD i=0;i<eidx;i++) if (entry[i].hObj==hObj) return entry[i].Albedo;
	return _V(1,1,1);
}

// ===========================================================================================
//
void FileParser::LogContent()
{
	LogAlw("FileParser: %u entries stored", eidx);

	for (DWORD i=0;i<eidx;i++) {
		char buf[256];
		if (entry[i].hObj) {
			oapiGetObjectName(entry[i].hObj, buf, 256);
			LogAlw("hObj(0x%X)='%s' File='%s'", entry[i].hObj, buf, entry[i].file);
		}
	}
}

// ===========================================================================================
//
bool FileParser::ParseScenario(const char *name)
{
	FILE* file = NULL;
	char cbuf[256];

	file = fopen(name, "r");

	if(file==NULL) {
		LogErr("Could not open a file '%s'", name);
		ParseSystem(Config->SolCfg);
		return true;
	}

	while(_fgets(cbuf, 256, file) != NULL) {
		if(!strncmp(cbuf, "BEGIN_ENVIRONMENT", 17))	{
			while(_fgets(cbuf, 256, file, true) != NULL) {
				if(!strncmp(cbuf, "System", 6))	{
					ParseSystem(cbuf+7);
					fclose(file);
					return true;
				}
			}
		}
	}
	LogErr("Failed to locate a system from a scenario '%s'", name);
	fclose(file);
	return false;
}

// ===========================================================================================
//
bool FileParser::ParseSystem(const char *_name)
{
	FILE* file = NULL;
	char cbuf[256];
	char name[256];
	sprintf_s(name, 256,"Config\\%s.cfg",_name);

	file = fopen(name, "r");

	if(file==NULL) {
		LogErr("Could not open a solar system file '%s'", name);
		return false;
	}

	while(_fgets(cbuf, 256, file) != NULL)
	{
		char *x = strchr(cbuf,'=');
		if (!strncmp(cbuf, "Name", 4)) continue;
		if (x) ParsePlanet(x+1);
	}

	fclose(file);
	return true;
}

// ===========================================================================================
//
bool FileParser::ParsePlanet(const char *_name)
{
	FILE* file = NULL;
	char cbuf[256];
	char name[256];
	sprintf_s(name, 256,"Config\\%s.cfg",_name);

	LogAlw("Parsing a planet %s",name);

	file = fopen(name, "r");

	if(file==NULL) {
		LogErr("Could not open a planet configuration file '%s'", name);
		return false;
	}

	char def[256]; bool bDefault = false;

	sprintf_s(def,256,"%s\\Base",_name);
	LogAlw("Default Path %s",def);

	OBJHANDLE hPlanet = NULL;
	DWORD pidx = 0;

	while(_fgets(cbuf, 256, file) != NULL) {

		if(!strncmp(cbuf, "Name=", 5))	{
			hPlanet = oapiGetObjectByName(cbuf+5);
			if (hPlanet) {
				pidx = eidx;
				entry[eidx].hObj = hPlanet;
				entry[eidx].file = new char[strlen(name)+1];
				strcpy(entry[eidx].file, name);
				eidx++;
			}
			else LogErr("Planet Not Found '%s'", cbuf+5);
		}

		if (hPlanet==NULL) continue;

		if(!strncmp(cbuf, "AlbedoRGB=", 10)) {
			VECTOR3 vec;
			sscanf(cbuf+10, "%lf %lf %lf", &vec.x, &vec.y, &vec.z);
			entry[pidx].Albedo = vec;
		}

		if(!strncmp(cbuf, "BEGIN_SURFBASE", 14)) {
			while(_fgets(cbuf, 256, file, true) != NULL) {
				if(!strncmp(cbuf, "DIR", 3)) {
					char *buf = cbuf+4;
					int l = strlen(buf);
					for (int i=0;i<l;i++) if (buf[i]=='/') buf[i]='\\';
					if(!strncmp(buf, "Config\\", 7)) buf+=7;  
					if(!strcmp(buf, def)) bDefault = true;
					ScanBases(hPlanet, buf);
				}
				if(!strncmp(cbuf, "END_SURFBASE", 12))	break;
			}	
		}
	}

	if (!bDefault) ScanBases(hPlanet, def);

	fclose(file);
	return true;
}

// ===========================================================================================
//
bool FileParser::ParseBase(OBJHANDLE hPlanet, const char *name)
{
	FILE* file = NULL;
	char cbuf[256];

	LogAlw("Parsing a base %s",name);

	file = fopen(name, "r");

	if (file==NULL) {
		LogErr("Could not open a base configuration file '%s'", name);
		return false;
	}

	while(_fgets(cbuf, 256, file) != NULL) {
		if(!strncmp(cbuf, "Name=", 5))	{
			OBJHANDLE hBase = oapiGetBaseByName(hPlanet, cbuf+5);
			if (hBase) {
				entry[eidx].hObj = hBase;
				entry[eidx].file = new char[strlen(name)+1];
				strcpy(entry[eidx].file, name);
				eidx++;
			}
			else LogErr("Object not found '%s'",cbuf+5);
			break;
		}
	}
	fclose(file);
	return true;
}


bool FileParser::ScanBases(OBJHANDLE hPlanet, const char *_name)
{
	_TRACE;

	char name[256];
	sprintf_s(name, 256,"Config\\%s",_name);

	LogAlw("Scanning bases from %s",name);

	if (hPlanet==NULL) {
		LogErr("hPlanet is NULL in FileParser::ScanBases(%s)", name);
		return false;
	}

	std::string     strFilePath;             // Filepath
	std::string     strPattern;              // Pattern
	std::string     strExtension;            // Extension
	HANDLE          hFile;                   // Handle to file
	WIN32_FIND_DATA FileInformation;         // File information


	strPattern = name;
	strPattern += "\\*.*";

	hFile = FindFirstFile(strPattern.c_str(), &FileInformation);

	if(hFile != INVALID_HANDLE_VALUE)
	{
		do
		{
			if(FileInformation.cFileName[0] != '.')
			{
				strFilePath.erase();
				strFilePath = name;
				strFilePath += "\\";
				strFilePath += FileInformation.cFileName;

				if(FileInformation.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
				{
					// DO NOT Search subdirectory
					//bool iRC = ScanBases(hPlanet, strFilePath.c_str());
					//if (iRC) return iRC;
				}
				else
				{
					// Check extension
					strExtension = FileInformation.cFileName;
					strExtension = strExtension.substr(strExtension.rfind(".") + 1);

					if(!strcmp(strExtension.c_str(), "cfg"))
					{
						ParseBase(hPlanet, strFilePath.c_str());
					}
				}
			}
		} while(FindNextFile(hFile, &FileInformation) == TRUE);

		// Close handle
		FindClose(hFile);

		DWORD dwError = GetLastError();
		if (dwError != ERROR_NO_MORE_FILES) LogErr("File Error in RunwayLights::SearchConfigFile() %u",dwError);
	}
	return false;
}